/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2023. All rights reserved.
 */

package util

import (
	"math"
	"math/rand"
	"strings"
	"time"

	"github.com/dlclark/regexp2"
	"github.com/google/uuid"
	"github.com/pkg/errors"
)

const (
	stringConnect = "#"
	InvalidString = ""
	EmptyString   = ""
	InvalidNumber = -1

	timeFormatLayout = "2006-01-02T15:04:05Z"
)

var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")

func MatchStr(pattern, str string) (bool, error) {
	reg, err := regexp2.Compile(pattern, 0)
	if err != nil {
		return false, errors.Errorf("MatchStr error: %v", err)
	}
	m, err := reg.FindStringMatch(str)
	if err != nil {
		return false, errors.Errorf("MatchStr error: %v", err)
	}
	if m != nil {
		return true, nil
	}
	return false, nil
}

func CombineTwoString(firstString, secondString string) string {
	//Concat
	var builder strings.Builder
	builder.WriteString(firstString)
	builder.WriteString(secondString)
	return builder.String()
}

func CombineStringWithConnect(partString []string) string {
	//Concat
	var builder strings.Builder
	for i := 0; i < len(partString); i++ {
		builder.WriteString(partString[i])
		if i != len(partString)-1 {
			builder.WriteString(stringConnect)
		}
	}
	return builder.String()
}
func GetStringFromConnect(oldString string) []string {
	ss := strings.Split(oldString, stringConnect)
	return ss
}
func InArray(target int, source []int) bool {
	for _, each := range source {
		if target == each {
			return true
		}
	}
	return false
}
func InStringArray(target string, source []string) bool {
	for _, each := range source {
		if target == each {
			return true
		}
	}
	return false
}

func GetDefaultTime() time.Time {
	return GetZeroTime(1970, 1, 1)
}

func GetZeroTime(year int, month time.Month, day int) time.Time {
	// 获取指定日期的0点时间
	return time.Date(year, month, day, 0, 0, 0, 0, time.UTC)
}
func IsDefaultTime(t time.Time) bool {
	defaultTime := GetDefaultTime()
	return t.Equal(defaultTime)
}

// 本地时间转UTC字符串 UTC时间，格式：yyyy-MM-dd'T'HH:mm:ss'Z'，如“2019-05-06T08:05:01Z”。 其中，HH范围是0～23，mm和ss范围是0～59。
func GetUTCStringFromLocalTime(t time.Time) string {
	utc := t.UTC()
	return utc.Format(timeFormatLayout)
}

// 时间直接转UTC字符串,默认t已经是UTC时间
func GetTimeString(t time.Time) string {
	return t.Format(timeFormatLayout)
}

// UTC字符串转time.Time,转换失败返回1970-1-1零点
func GetTimeFromUTCStr(utc string) (time.Time, error) {
	t, err := time.Parse(timeFormatLayout, utc)
	if err != nil {
		return GetDefaultTime(), err
	}
	return t, nil
}

// 时间转UTC时间
func GetUTC(t time.Time) time.Time {
	return t.UTC()
}

// 时间转UTC毫秒数
func GetMilliSec(time time.Time) int64 {
	return time.UnixMilli()
}

// utc毫秒数转UTC时间
func GetUTCFromMilliSec(timeSecond *int64) *time.Time {
	if timeSecond == nil {
		return nil
	}
	time := time.UnixMilli(*timeSecond).UTC()
	return &time
}

// utc毫秒数转UTC字符串
func GetStringFromMilliSec(timeSecond *int64) *string {
	if timeSecond == nil {
		return nil
	}
	utcTime := time.UnixMilli(*timeSecond)
	utc := GetTimeString(utcTime)
	return &utc
}

// utc时间转utc秒数
func GetUnixTime(time time.Time) int64 {
	return time.Unix()
}

// utc秒数转utc时间
func GetUTCUnixSec(timeSecond *int64) *time.Time {
	if timeSecond == nil {
		return nil
	}
	time := time.Unix(*timeSecond, 0)
	return &time
}

// 当前时间的东八区时间,失败返回默认时间
func GetGMT8TimeNow() (*time.Time, error) {
	utcTime := time.Now().UTC()
	loc, err := time.LoadLocation("Asia/Shanghai")
	if err != nil {
		return nil, err
	}
	nowTime := utcTime.In(loc)
	return &nowTime, nil
}

func Float64Equal(a, b, epsilon float64) bool {
	return math.Abs(a-b) < epsilon
}
func Float64Larger(a, b, epsilon float64) bool {
	return (a - b) > epsilon
}
func Float64Smaller(a, b, epsilon float64) bool {
	return (a - b) < epsilon
}

// GetUUID 生成v4版本的uuid--36位
func GetUUID() string {
	uid := uuid.New()
	key := uid.String()
	return key
}
func GetUUID32() string {
	return GetUUIDNotCrossbar()
}

// GetUUIDNotCrossbar 生成v4版本的uuid--32位
func GetUUIDNotCrossbar() string {
	uid := GetUUID()
	uid = strings.Replace(uid, "-", "", -1)
	return uid
}

func GetIndexFromUUID() string {
	key := GetUUIDNotCrossbar()
	//collectionIndex必须以字母开头
	rand.Seed(time.Now().UnixNano())
	index := rand.Intn(len(letters) - 1)
	firstAlphabet := letters[index]
	uid := CombineTwoString(string(firstAlphabet), key[1:])
	return uid
}
